﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

using Microsoft.SharePoint.Administration;

namespace Mystery.SharePoint
{
    /// <summary>
    /// Settings for site provisioning
    /// </summary>
    [Guid("21EF60E0-9162-4414-AD96-8A0BF3DD2857")]
    public class SiteProvisioningSettings : SPPersistedObject
    {
        private const string ObjectName = "SPM.SiteProvisioningSettings";
        private const string Seperator = ";";

        [Persisted]
        private string _authenticationProvidersEncoded = string.Empty;
        [Persisted]
        private string _webTemplatesEncoded = string.Empty;
        [Persisted]
        private string _activeAuthenticationProvider = string.Empty;

        private List<string> _defaultAuthenticationProvidersList = null;
        private List<string> _authenticationProvidersList = null;
        private List<string> _webTemplatesList = null;

        private List<string> DefaultAuthenticationProvidersList
        {
            get
            {
                if (_defaultAuthenticationProvidersList == null)
                {
                    _defaultAuthenticationProvidersList = new List<string>();
                    _defaultAuthenticationProvidersList.Add(typeof(EveryoneSiteProvisioningAuthenticationProvider).AssemblyQualifiedName);
                    _defaultAuthenticationProvidersList.Add(typeof(MemberSiteProvisioningAuthenticationProvider).AssemblyQualifiedName);
                }
                return _defaultAuthenticationProvidersList;
            }
        }

        /// <summary>
        /// Gets and array of authentication provides that are available
        /// </summary>
        public string[] AuthenticationProviders 
        {
            get
            {
                return _authenticationProvidersList.ToArray<string>();
            }
            set
            {
                if (value.Contains(this.ActiveAuthenticationProvider) == false)
                {
                    throw new InvalidOperationException("Cannot remove the currently active Authentication provider");
                }
                _authenticationProvidersList = new List<string>(value);
                _authenticationProvidersList.AddRange(this.DefaultAuthenticationProvidersList);
            }
        }
        /// <summary>
        /// Gets an array of web templates that are available
        /// </summary>
        public string[] WebTemplates
        {
            get
            {
                return _webTemplatesList.ToArray<string>();
            }
            set
            {
                _webTemplatesList = new List<string>(value);
            }
        }
        /// <summary>
        /// Gets or sets the full name of the authentication provider
        /// </summary>
        public string ActiveAuthenticationProvider 
        {
            get { return _activeAuthenticationProvider; }
            set 
            {
                if (this._authenticationProvidersList.Contains(value) == false)
                {
                    throw new InvalidOperationException(
                        string.Format(null, "Cannot assign {0} as the active authentication provide since it's not part of the available providers",
                        value));
                }
                _activeAuthenticationProvider = value; 
            }
        }

        internal SiteProvisioningSettings(string name, SPPersistedObject parent)
            : base(name, parent)
        {
            // the first time the code runs, nothing has been serialized so we need to fill things in
            _webTemplatesList = new List<string>();
            _authenticationProvidersList = new List<string>();
            _authenticationProvidersList.AddRange(this.DefaultAuthenticationProvidersList);
        }
        /// <summary>
        /// Default constructor used for serialization
        /// </summary>
        [Obsolete("This should only be used by the serialization engine", true)]
        public SiteProvisioningSettings()
            : base()
        {
        }
        protected override void OnDeserialization()
        {
            base.OnDeserialization();

            // create the temporary lists that we perform most of the operations against
            _authenticationProvidersList = _authenticationProvidersEncoded.CreateList(Seperator);
            _webTemplatesList = _webTemplatesEncoded.CreateList(Seperator);

            // make sure that our generic ones are always present
            _authenticationProvidersList.AddRange(this.DefaultAuthenticationProvidersList);
        }
        internal static SiteProvisioningSettings Create(SPWebApplication application)
        {
            if (application == null) throw new ArgumentNullException("application");

            SiteProvisioningSettings settings = application.GetChild<SiteProvisioningSettings>(SiteProvisioningSettings.ObjectName);
            if (settings == null)
            {
                settings = new SiteProvisioningSettings(SiteProvisioningSettings.ObjectName, application);
                settings.Update();
            }
            return settings;
        }
        /// <summary>
        /// Creates an object representing the active authentication provider
        /// </summary>
        /// <returns></returns>
        public ISiteProvisioningAuthenticationProvider CreateAuthenticationProvider()
        {
            if (string.IsNullOrEmpty(this.ActiveAuthenticationProvider) == true)
            {
                return null;
            }
            return ProvisioningUtilities.CreateObjectFromString<ISiteProvisioningAuthenticationProvider>(this.ActiveAuthenticationProvider);
        }

        public override void Update()
        {
            // update our persisted objects with data from our temporary lists
            _webTemplatesEncoded = _webTemplatesList.CreateSeperatedString(Seperator);
            _authenticationProvidersEncoded = _authenticationProvidersList.CreateSeperatedString(Seperator);

            base.Update();
        }
    }
}
